package cn.com.dhcc.tlq;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;


/**
 * 使用apache 的common-compress.jar打包
 * tar 对文件进行打包处理,仅仅是打包，不压缩
 * 
 * 打包输出流对象TarArchiveOutputStream
 * 构造一个tar实体对象  TarArchiveEntry
 * 然后往输出流对象put一个tar实体对象,将文件流写入到输出流对象
 * 
 * 构造一个输出流对象
 * 
 * @日期 2015-12-25 上午10:29:24
 * @作者  高强
 */
public class FilePacketUtil {
	
	
	/**
	 * 缓冲区大小
	 */
	protected static int BUFFERD_LENTH=2048;
	
	/**
	 * 默认的编码
	 */
	protected static String DEFAULT_ENCODING="UTF-8";

	
	
	/**
	 * 打包一个文件
	 * @param srcFile 要打包的文件，可以是一个文件，也可以是一个文件夹
	 * @param out  打包输出流
	 * @param basePath 打包的基本路径，打包的目录结构
	 * @throws IOException
	 */
	protected  static void tar(File srcFile,TarArchiveOutputStream out,String basePath) throws IOException{
		if (srcFile.isFile()) {
			tarFile(srcFile, out, basePath);
		}else{
			tarDir(srcFile, out, basePath);
		}
	}
	
	/**
	 * 打包一个字符串，生成后缀为.tar
	 * @param srcStr要打包的字符串
	 * @param srcPathName 打包字符串生成的名称
	 * @param out  输出流
	 * @param basePath 基本路径
	 * @throws IOException 
	 */
	protected static void tarString(String srcStr,String srcName,TarArchiveOutputStream out,String basePath) throws IOException{
		byte[] strByte=srcStr.getBytes(DEFAULT_ENCODING);
		TarArchiveEntry entry=new TarArchiveEntry(basePath+srcName);
		entry.setSize(strByte.length);
		out.putArchiveEntry(entry);
		IOUtils.copy(new BufferedInputStream(new ByteArrayInputStream(strByte)), out, BUFFERD_LENTH);
		out.closeArchiveEntry();
	}
	
	
	/**
	 * 打包一个文件，生成后缀为.tar
	 * @param srcFile
	 * @param out
	 * @param basePath
	 * @throws IOException 
	 */
	protected static void tarFile(File srcFile,TarArchiveOutputStream out,String basePath) throws IOException{
		if (!srcFile.isFile()) {
			throw new IOException("the method srcFile() must accpet a file,not a directory");
		}
		
		TarArchiveEntry entry=new TarArchiveEntry(basePath+srcFile.getName());
		entry.setSize(srcFile.length());
		out.putArchiveEntry(entry);
		IOUtils.copy(new BufferedInputStream(new FileInputStream(srcFile)), out, BUFFERD_LENTH);
		
		out.closeArchiveEntry();
	}
	
	/**
	 * 打包一个目录，并且保持目录结构
	 * @param srcDir 要打包的文件夹
	 * @param out  输出流
	 * @param basePath 基本路径
	 * @throws IOException
	 */
	protected static void tarDir(File srcDir,TarArchiveOutputStream out,String basePath) throws IOException{
		if (!srcDir.isDirectory()) {
			throw new IOException("the method tarDir() must accpet a directory,not a file");
		}
		
		TarArchiveEntry entry=new TarArchiveEntry(basePath+srcDir.getName()+File.separator);
		out.putArchiveEntry(entry);
		out.closeArchiveEntry();
		basePath=basePath+srcDir.getName()+File.separator;//basePath变化
		File[] fs=srcDir.listFiles();
		if (fs==null || fs.length<=0) {
			return;
		}
		for (int i = 0; i < fs.length; i++) {
			File file = fs[i];
			tar(file, out, basePath);
		}
		
	}
	
	/**
	 * 打包处理
	 * @param sources
	 * @param out
	 * @throws FileNotFoundException
	 */
	protected static void tarProcess(List<?> sources,TarArchiveOutputStream out) throws FileNotFoundException {
		 //打包每一个文件
	   	 for (Object src : sources) {
	   		try {
	   			File srcFile=null;
	   			if (src instanceof String) {
	   				srcFile=new File(src.toString());
					}else if(src instanceof File){
						srcFile=(File)src;
						if (srcFile.isDirectory()) {//目录忽略
							continue;
						}
					}else{//其他类型忽略
						continue;
					}
	   			tar(srcFile, out, "");
				} catch (IOException e) {
					e.printStackTrace();
				}
	   	 }
	}
	
	
	/**
	 * 对多个文件进行打包处理
	 * @param srcDir 要打包的文件夹
	 * @param tarName (要打包的名称路径，绝对路径)
	 * @return 打包的文件的路径
	 */
	public static String tar(File srcDir,String target){
		
		
		return null;
	}
	
	
	/**
	 * 对多个文件进行打包处理
	 * @param srcPaths 要打包的文件集合,或者文件名称集合
	 * @param tarName (要打包的名称路径，绝对路径)
	 * @return 打包的文件的路径
	 */
	public static String tar(List<?> sources,String target){
		return tar(sources, new File(target));
	}
	
	/**
	 * 对多个文件进行打包处理
	 * @param srcPaths 要打包的文件集合,或者文件名称集合
	 * @param tarName (要打包成的文件)
	 * @return 打包的文件的路径
	 */
	public static String tar(List<?> sources,File target){
		 TarArchiveOutputStream out = null;  
    	//构造输出流
    	 try {
    		 out = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(target)),DEFAULT_ENCODING); //输出流
    		 tarProcess(sources, out);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}finally{//资源关闭
			if (out!=null) {
				IOUtils.closeQuietly(out);
			}
		}
		return target.getAbsolutePath();
	}
	
	
	
	
	/**
	 * 解包一个文件
	 * @param is 输出流
	 * @param destFile 解包成的文件
	 * @throws IOException 
	 */
	private static void untarFile(TarArchiveInputStream is,File destFile) throws IOException{
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));  
		int count;  
	    byte data[] = new byte[BUFFERD_LENTH];  
	    while ((count = is.read(data, 0, BUFFERD_LENTH)) != -1) {  
	        bos.write(data, 0, count);  
	    }
	    bos.close();
	}
	
	
	
	/**
	 * 解包
	 * @param tarFile 要解包的文件
	 * @return
	 * @throws IOException 
	 */
	public static String untar(String tarFile){
		return untar(tarFile, new File(tarFile).getParent());
	}
	/**
	 * 解包
	 * @param tarFile 要解包的文件
	 * @param target 解包到的目录
	 * @return
	 * @throws IOException 
	 */
	public static String untar(String tarFile,String target){
		File basePath=new File(target);
		TarArchiveInputStream is=null;
		try {
			is=new TarArchiveInputStream(new FileInputStream(new File(tarFile)), DEFAULT_ENCODING);
			TarArchiveEntry entry=null;
			while ((entry=is.getNextTarEntry())!=null) {
				
				File ef=new File(basePath, entry.getName());
				if (entry.isDirectory()) {//如果是一个目录
					ef.mkdirs();//创建目录
				}else{
					if (!ef.getParentFile().exists()) {//创建父级目录
						ef.getParentFile().mkdirs();
					}
					untarFile(is, ef);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (is!=null) {
				IOUtils.closeQuietly(is);
			}
		}
		
		return basePath.getAbsolutePath();
	}
	
	public static void main(String[] args) {
		List<File> list=new ArrayList<File>();
		list.add(new File("E:\\log4j.properties"));
		list.add(new File("E:\\测试.txt"));
		list.add(new File("E:\\ResourceOne BizFoundation基础开发平台5.0.5开发指南_1.0.pdf"));
		Date d=new Date();
		System.out.println();
		System.out.println(tar(list, new File("E:\\bootstrap\\mytar.tar")));
		System.out.println("打包花费时间"+(new Date().getTime()-d.getTime())+"毫秒");
		d=new Date();
		System.out.println(untar("E:\\bootstrap\\mytar.tar"));
		System.out.println("解包花费时间"+(new Date().getTime()-d.getTime())+"毫秒");
	}
	
}
